package it.uniroma2.art.owlart.owlimimpl.models;

import org.openrdf.model.Resource;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryException;
import org.openrdf.sail.SailException;

import it.uniroma2.art.owlart.exceptions.ModelCreationException;
import it.uniroma2.art.owlart.model.ARTResource;
import it.uniroma2.art.owlart.model.NodeFilters;
import it.uniroma2.art.owlart.models.BaseRDFTripleModel;
import it.uniroma2.art.owlart.models.OWLReasoner;
import it.uniroma2.art.owlart.models.RDFSReasoner;
import it.uniroma2.art.owlart.owlimimpl.reasoning.RuleSet;
import it.uniroma2.art.owlart.sesame2impl.models.BaseRDFModelSesame2Impl;

public class BaseRDFModelOWLIMImpl extends BaseRDFModelSesame2Impl implements BaseRDFTripleModel,
		RDFSReasoner, OWLReasoner {

	RuleSet reasoningLevel;

	public BaseRDFModelOWLIMImpl(Repository repo, RuleSet level) throws SailException, RepositoryException,
			ModelCreationException {
		super(repo, true);
		reasoningLevel = level;
		rdfsReasoning = reasoningLevel.isRDFSReasoning();
	}

	/**
	 * this method has been rewritten as of the difference between Sesame2 and OWLIM triple stores in in
	 * handling non-explicit statements inside their graphs.<br/>
	 * When queried with the inference argument set to true:
	 * <ul>
	 * <li>Sesame2 assigns to the default graph not only those statements originated from inference, but also
	 * those coming from the other graphs (though considering them as non-explicit)</li>
	 * <li>OWLIM assigns to the default graph (as non-explicit statements) only those statements originated by
	 * inference</li>
	 * </ul>
	 * 
	 * @param inference
	 * @param graphs
	 * @return
	 */
	protected Resource[] getSesameContextsForREAD(boolean inference, ARTResource... graphs) {
		// TODO make the withInference behaviour selectable through OWLART API, like with an option where the
		// user can decide if literally respecting the named graphs list or if "no repetitions" should be
		// guaranteed at the cost of shifting the graphs (but still respecting the triples to be asked, that
		// is, the maingraph can be returned in place of specific graphs if maingraph or any are selected)

		if (graphs == null)
			throw new IllegalArgumentException();
		if (inference && (graphs.length == 0)) {
			// in case of inference returns the sole nullContext, which will be read only one time
			// and contains all the triples in the store
			return createNullContext();
		}

		Resource[] resContexts = new Resource[graphs.length];
		for (int i = 0; i < graphs.length; i++) {
			if (graphs[i] == null)
				throw new IllegalArgumentException("a null value cannot be accepted as a named graph");
			// a null value for a contest is not accepted in OWLArt
			// (though in Sesame it means: null-context), null-context (main unnamed graph) in OWLArt must be
			// specified as MAINGRAPH
			else if (graphs[i] == NodeFilters.ANY)
				// if any of the graphs is ANY, then an empty array is sent to Sesame (which interpretes as
				// all graphs when reading/deleting and maingraph when adding triples)
				// TODO could be implemented, when writing, as a special NodeFilter/graphs which always fails
				// the equals
				if (inference) {
					// in case of inference returns the sole nullContext, which will be read only one time
					// and contains all the triples in the store
					return createNullContext();
				} else
					return new Resource[0];
			else if (graphs[i] == NodeFilters.MAINGRAPH) {
				if (inference) {
					// in case of inference returns the sole nullContext, which will be read only one time
					// and contains all the triples in the store
					return createNullContext();
				} else
					resContexts[i] = null; // in Sesame, MAINGRAPH is implemented with null on the graphs
			}

			else
				resContexts[i] = ses2artFact.aRTResource2SesameResource(graphs[i]);
		}
		return resContexts;
	}

	// TODO verificare
	public boolean supportsOWLThingMaterialization() {
		return reasoningLevel.isAtLeastHorst();
	}

	// TODO verificare
	public boolean supportsTransitiveProperties() {
		return reasoningLevel.isAtLeastHorst();
	}

	// TODO verificare
	public boolean supportsInverseProperties() {
		return reasoningLevel.isAtLeastHorst();
	}

	// TODO verificare
	public boolean supportsSymmetricProperties() {
		return reasoningLevel.isAtLeastHorst();
	}

}
